package models

import (
	//init postgres db
	"database/sql"
	"strings"

	//init postgres db
	_ "github.com/lib/pq"

	"crypto/md5"
	"encoding/hex"
	"encoding/json"
)

// NewUser 新用户注册信息
type NewUser struct {
	WechatID string `json:"wechat_id"`
	Mobile   string `json:"mobile"`
	Pass     string `json:"pass"`
	Nickname string `json:"nickname"`
}

// BasicInfo 基本信息
type BasicInfo struct {
	RealName     string `json:"realname"`
	Location     string `json:"location"`
	Gender       string `json:"gender"`
	Birthdate    string `json:"birthdate"`
	BloodType    string `json:"bloodtype"`
	Introduction string `json:"introduction"`
}

// 证件种类
const (
	IDCARD = "idcard"
)

// KycInfo 认证信息
type KycInfo struct {
	Type string `json:"type"`
	No   string `json:"no"`
}

// User 用户表
type User struct {
	ID        int64      `json:"id"`
	UUID      string     `json:"uuid"`
	WechatID  string     `json:"wechat_id"`
	Mobile    string     `json:"mobile"`
	Email     string     `json:"email"`
	Pass      string     `json:"pass"`
	Nickname  string     `json:"nickname"`
	Avatar80  []byte     `json:"avatar80"`
	Avatar50  []byte     `json:"avatar50"`
	Avatar30  []byte     `json:"avatar30"`
	BasicInfo *BasicInfo `json:"basic_info"`
	KycInfo   *KycInfo   `json:"kyc_info"`
}

func md5encode(raw string) string {
	h := md5.New()
	h.Write([]byte(raw))
	cipherStr := h.Sum(nil)
	str := hex.EncodeToString(cipherStr)
	return str
}

// CreateUserByMobile 用短信注册时用这个
func CreateUserByMobile(mobile string, pass string) (user *NewUser, err error) {

	nuser := &NewUser{
		Mobile: mobile,
		Pass:   md5encode(pass),
	}
	_, err = db.Exec(
		"INSERT INTO users (mobile, nickname, pass) VALUES ($1, $2, $3) returning id;",
		nuser.Mobile,
		nuser.Mobile,
		nuser.Pass)

	// 抓取 手机号已存在错误
	if err != nil &&
		err.Error() == `pq: duplicate key value violates unique constraint "users_mobile_key"` {
		err = ErrExisted
		return
	}

	// 其他错误
	if err != nil {
		return
	}

	user = nuser
	return
}

func formatUser(row *sql.Row) (*User, error) {
	u := &User{}
	var (
		basicinfo []byte
		kycinfo   []byte
		wechatid  sql.NullString
		mobile    sql.NullString
		email     sql.NullString
	)
	err := row.Scan(
		&u.ID,
		&u.UUID,
		&wechatid,
		&mobile,
		&email,
		&u.Pass,
		&u.Nickname,
		&u.Avatar80,
		&u.Avatar50,
		&u.Avatar30,
		&basicinfo,
		&kycinfo)

	// 抓取 用户不存在错误
	if err == sql.ErrNoRows {
		err = ErrNotFound
		return u, err
	}

	b := &BasicInfo{}
	if err = json.Unmarshal(basicinfo, &b); err != nil {
		return u, err
	}
	k := &KycInfo{}
	if err = json.Unmarshal(kycinfo, &k); err != nil {
		return u, err
	}
	u.BasicInfo = b
	u.KycInfo = k

	if wechatid.Valid {
		u.WechatID = strings.TrimSpace(wechatid.String)
	}

	if mobile.Valid {
		u.Mobile = strings.TrimSpace(mobile.String)
	}

	if email.Valid {
		u.Email = strings.TrimSpace(email.String)
	}

	u.Nickname = strings.TrimSpace(u.Nickname)

	return u, err
}

func formatBasicInfo(row *sql.Row) (bi *BasicInfo, err error) {
	bi = &BasicInfo{}
	var biBytes []byte
	e := row.Scan(
		&biBytes,
	)
	e = json.Unmarshal(biBytes, &bi)
	if e != nil {
		err = e
		return
	}
	return
}

// GetUserByUUID 通过uuid查找用户
func GetUserByUUID(uuid string) (*User, error) {
	row := db.QueryRow("SELECT id, uuid, wechat_id, mobile, email, pass, nickname, avatar80, avatar50, avatar30, basic_info, kyc_info FROM users WHERE uuid=$1;", uuid)
	user, err := formatUser(row)
	return user, err
}

// GetUserByMobile 通过手机号查找用户
func GetUserByMobile(mobile string) (*User, error) {
	row := db.QueryRow("SELECT id, uuid, wechat_id, mobile, email, pass, nickname, avatar80, avatar50, avatar30, basic_info, kyc_info FROM users WHERE mobile=$1;", mobile)
	user, err := formatUser(row)
	return user, err
}

// GetUserByMobileAndPass 通过手机号和密码查找用户
func GetUserByMobileAndPass(mobile string, pass string) (*User, error) {
	row := db.QueryRow("SELECT id, uuid, wechat_id, mobile, email, pass, nickname, avatar80, avatar50, avatar30, basic_info, kyc_info FROM users WHERE mobile=$1 AND pass=$2;",
		mobile, md5encode(pass))
	user, err := formatUser(row)
	return user, err
}

// UpdateUserBasicInfoByUUID 更新基本信息
func UpdateUserBasicInfoByUUID(uuid string, basicinfo *BasicInfo) error {
	bytes, e := json.Marshal(basicinfo)
	if e != nil {
		return e
	}
	basicinfoStr := string(bytes)
	_, e = db.Exec("UPDATE users SET basic_info=$1 WHERE uuid=$2;", basicinfoStr, uuid)
	if e != nil {
		return e
	}
	return nil
}

// GetUserBasicInfoByUUID 查询用户基本信息
func GetUserBasicInfoByUUID(uuid string) (bi *BasicInfo, err error) {
	row := db.QueryRow("SELECT basic_info FROM users WHERE uuid=$1", uuid)
	bi, e := formatBasicInfo(row)
	if e != nil {
		err = e
		return
	}
	return
}

// UpdateKycInfo 更新认证信息
// UpdateAvatar 更新头像
// UpdateNickName 更新昵称
// UpdatePass 更新密码
